<template>
  <n-modal
    v-model:show="itrainState.showModal"
    transform-origin="center"
    preset="card"
    title="进行类别选择"
    class="w-600"
  >
    <template #default>
      <div>
        <n-space vertical>
          <div>{{ itrainState.msg }}</div>
          <n-space v-if="itrainState.catOptions.length > 0" vertical>
            <div class="flex items-center">
              <p>切换到题目类别：</p>
              <n-select
                v-model:value="itrainState.catId"
                :options="itrainState.catOptions"
                class="max-w-200"
                @update:value="handleSelect"
              />
            </div>
            <div class="mt-5 color-gray-500">
              <div v-if="catDesc.length > 0">类别描述：{{ catDesc }}</div>
            </div>
            <div class="mt-10">
              <b>注意：一旦抽取新题，即开始计时。请预留足够时间才开始做题。</b>
            </div>
          </n-space>
        </n-space>
      </div>
    </template>
    <template #footer>
      <n-space v-if="itrainState.drawProblem" justify="space-around">
        <n-button type="primary" @click="drawProblem(examId, itrainState.catId, router)">
          我要抽题
        </n-button>
        <n-button @click="itrainState.showModal = false">暂且返回</n-button>
      </n-space>
      <n-space v-else justify="center">
        <n-button @click="itrainState.showModal = false">确定</n-button>
      </n-space>
    </template>
  </n-modal>
  <div v-show="loading" class="min-h-100 f-c-c">
    <Loading />
  </div>
  <div v-show="!loading" class="h-full overflow-auto">
    <div class="flex px-4 py-10">
      <div class="w-120">运行结果</div>
      <div>{{ result ? result.status : '' }}</div>
    </div>
    <div class="flex px-4 py-10">
      <div class="w-120">提交次数</div>
      <div>{{ result ? result.submit : '0' }}</div>
    </div>
    <div class="flex px-4 py-10">
      <div class="w-120">所得分数</div>
      <div>{{ result ? (result.score <= 0 ? '暂时没有分数' : result.score) : '' }}</div>
    </div>
    <div class="flex px-4 py-10">
      <div class="w-120">正确测试用例ID</div>
      <div
        v-if="
          result &&
          result.correctCaseIds &&
          result.correctCaseIds.length &&
          result.correctCaseIds[0] != '-1'
        "
        class="flex flex-wrap items-center gap-10"
      >
        <div v-for="item in result?.correctCaseIds" :key="item">
          {{ item }}
        </div>
      </div>
    </div>
    <div class="flex items-center px-4 py-10">
      <div class="w-120">错误测试用例ID</div>
      <div
        v-if="result && result.wrongcases && result.wrongcases.length"
        class="flex items-center gap-10 text-18"
      >
        <div v-for="item in result.wrongcases" :key="item.id" class="f-c-c gap-2">
          <span>{{ item.caseId }}</span>
          <SvgIcon
            icon="tips"
            class="h-18 w-18 cursor-pointer"
            @click="handleShowCase(item.caseId, item.id)"
          />
        </div>
      </div>
    </div>
    <div v-if="result && result.wrongcases && result.wrongcases.length" flex px-90>
      <n-button text style="color: cadetblue; font-size: 13px" @click="questionShow">
        为什么OJ上的运行结果和我本机结果不一样？
      </n-button>
    </div>
    <div v-if="canSubmitProblem" class="flex px-4 py-10">
      <div class="w-120">提交本题</div>
      <n-button type="primary" @click="onSubmitProblem">点我提交</n-button>
    </div>
    <div v-else class="flex px-4 py-10">
      <div class="w-120">提交本题</div>
      <div class="color-green">已提交</div>
    </div>

    <div class="flex px-4 py-10">
      <div class="w-120">详细信息</div>
      <n-input :value="result ? result.remark : ''" type="textarea" rows="10"></n-input>
    </div>

    <!--  -->
    <!-- <div class="flex items-center px-4 py-10">
      <div class="w-120">代码优化</div>
      <n-button type="primary" :disabled="codeAnalyseButtonDisabled" @click="codeAnalyse">
        代码分析
      </n-button>
      <n-button
        class="ml-20"
        type="primary"
        :disabled="codeAnalyseButtonDisabled"
        @click="codeOptimize"
      >
        代码优化
      </n-button>
      <div class="ml-10">{{ waitingTime }}</div>
    </div>
    <div class="mb-5">
      <n-input type="textarea" rows="10" :value="codeFuseResCode" placeholder="代码分析结果" />
    </div> -->

    <!-- 查看用例Modal -->
    <n-modal v-model:show="showCaseModal" size="huge" :bordered="false">
      <div class="relative min-w-370 w-3/4 rounded-10 bg-white px-28 py-16 dark:bg-dark">
        <n-button class="absolute right-24 top-20 rounded" text style="font-size: 24px">
          <SvgIcon icon="close" color="black" @click="handleCloseCaseModal" />
        </n-button>

        <h3 class="text-24 font-normal">查看测试用例</h3>
        <h4 class="py-8 text-18 font-normal">测试用例ID：{{ caseObj?.problemtestcases.id }}</h4>
        <div class="mb-10">
          <div class="flex items-center pb-8">
            <h4>测试用例输入</h4>
            <!-- <CopyButton
              :text="caseObj?.problemtestcases.input"
              pop-msg="复制测试用例输入"
            ></CopyButton> -->
          </div>
          <n-input
            type="textarea"
            rows="6"
            placeholder=""
            :value="caseObj?.problemtestcases.input"
          />
        </div>
        <div class="flex flex-wrap gap-16">
          <div class="min-w-200 flex-1">
            <div class="flex justify-between pb-8">
              <div class="flex items-center">
                <h4>测试用例正确输出</h4>
                <!-- <CopyButton
                  :text="
                    asciiActive
                      ? getAscii(caseObj?.problemtestcases.output)
                      : caseObj?.problemtestcases.output
                  "
                  pop-msg="复制测试用例正确输出"
                ></CopyButton> -->
              </div>
              <div>
                显示为ASCII码
                <n-switch v-model:value="asciiActive" size="small" />
              </div>
            </div>
            <n-input
              type="textarea"
              rows="6"
              placeholder=""
              :value="
                asciiActive
                  ? getAscii(caseObj?.problemtestcases.output)
                  : caseObj?.problemtestcases.output
              "
            />
          </div>
          <div class="min-w-200 flex-1">
            <div class="flex items-center pb-8">
              <h4>你的用例输出</h4>
              <!-- <CopyButton
                :text="
                  asciiActive ? getAscii(caseObj?.wrongcases.output) : caseObj?.wrongcases.output
                "
                pop-msg="复制你的用例输出"
              ></CopyButton> -->
            </div>
            <n-input
              type="textarea"
              rows="6"
              placeholder=""
              :value="
                asciiActive ? getAscii(caseObj?.wrongcases.output) : caseObj?.wrongcases.output
              "
            />
          </div>
        </div>
      </div>
    </n-modal>
  </div>
</template>

<script setup>
import api from '@/api/user'
import Loading from '@/components/common/Loading.vue'
import { useRouter } from 'vue-router'
import { PROBLEM_TAB_NAMES, STATUS } from '@/constant'
import { submitProblem, itrainState, drawProblem } from './utils.js'
import CopyButton from '../common/CopyButton.vue'

const router = useRouter()

const LeftListFrequency = 6000

const { examId, problemId, catId, continueTrain } = inject('problem/idsValue', {})
const exam = inject('problem/exam')
const problem = inject('problem/problem')
const activeTab = inject('problem/activeTab')
const canSubmitProblem = inject('problem/canSubmitProblem')
// const lastSubmittedCode = inject('problem/lastSubmittedCode')
const lastSubmittedCodeTime = inject('problem/lastSubmittedCodeTime')
const result = inject('problem/lastSubmittedResult')

const getAllWrongAndRightCasesApi = inject('problem/getAllWrongAndRightCasesApi')
const getCaseHintApi = inject('problem/getCaseHintApi')

const resultTimer = ref(null)

const loading = ref(false)

const showCaseModal = ref(false)
const caseObj = ref(null)

const catDesc = ref('') // 题目类别描述
const catInfoMap = new Map() // 类别信息哈希表

const handleSelect = (value) => {
  getCatDescAndTimelimit(value)
}

// 获取类别描述信息和时间限制信息
const getCatDescAndTimelimit = async (catId) => {
  if (!catInfoMap.has(catId)) {
    try {
      const res = await api.getCatDescriptionAndTimelimit({
        params: { secCatgory_id: catId, examId: examId },
      })
      catDesc.value = res.data.description
      catInfoMap.set(catId, res.data)
    } catch (error) {
      console.log(error)
      $message.error('获取类别描述信息和时间限制信息失败')
    }
  } else {
    catDesc.value = catInfoMap.get(catId).description
  }
}

// 请求运行结果
const getProblemResult = async (needLoading = true) => {
  try {
    loading.value = needLoading
    const caseRes = await getAllWrongAndRightCasesApi()
    result.value = caseRes.data
  } catch (err) {
    console.log(err)
  } finally {
    loading.value = false
  }
}

// 提交本题
const onSubmitProblem = async () => {
  if (!result.value) {
    $message.error('未提交过代码，所以无法提交本题!')
    return
  }
  return submitProblem({
    examId: examId,
    submitOnlyAC: !!exam.value?.submitOnlyAC,
    problemId: problemId,
    problemTitle: problem.value?.title,
    problemStatus: result.value.status || '',
    problemScore: result.value.score || '',
    catId,
    continueTrain,
    successCallback: () => {
      //修改成不可提交
      canSubmitProblem.value = false
    },
  })
}

const handleShowCase = (caseId, id) => {
  $dialog.warning({
    title: '查看测试用例',
    content: `查看当前题目的正确测试用例会减少该题相应的得分，但查看同一个测试用例不会重复扣分。
你确认要查看正确的测试用例吗？`,
    positiveText: '确认',
    negativeText: '取消',
    onPositiveClick: async () => {
      if (!exam.value) {
        return
      }
      if (!exam.value.canGetHint) {
        $notification.error('该场考试不允许获取提示')
        return
      }
      showCaseModal.value = true
      try {
        // caseId:问题的用例, id:学生提交后产生的错误测试用例
        const res = await getCaseHintApi(caseId, id)
        caseObj.value = res.data
        // 重新请求
        getProblemResult(false)
      } catch (err) {
        console.log(err)
      }
    },
  })
}
const questionShow = () => {
  window.open(`http://${window.location.host}/#/user/faq?expandItem=13&itemId=collapse13`, '_blank')
}
const handleCloseCaseModal = () => {
  showCaseModal.value = false
  asciiActive.value = false
  caseObj.value = null
}

const asciiActive = ref(false)

//获取ascii码，ascii码以空格分开
const getAscii = (str) => {
  if (!str) return ''
  let strAscii = '' //用于接收ASCII码
  for (let i = 0; i < str.length; i++) {
    if (str.charCodeAt(i) != 10) {
      if (str.charCodeAt(i) != 13) {
        //将\r过滤掉
        strAscii = strAscii + str.charCodeAt(i) + ' ' //把字符串中的字符一个一个的解码
      }
    } else strAscii = strAscii + str.charCodeAt(i) + '\n'
  }
  return strAscii
}

watch(lastSubmittedCodeTime, () => {
  //重新加载结果
  getProblemResult()
    .then(() => {
      // 定时轮询
      if (resultTimer.value) {
        clearInterval(resultTimer.value)
        resultTimer.value = null
      }
      if (result.value) {
        resultTimer.value = setInterval(async () => {
          try {
            const caseRes = await getAllWrongAndRightCasesApi()
            result.value = caseRes.data
            if (![STATUS.QUEUE, STATUS.WAIT].includes(result.value.status)) {
              // 停止轮询
              if (resultTimer.value) {
                clearInterval(resultTimer.value)
                resultTimer.value = null
              }
            }
          } catch (error) {
            // 停止轮询
            if (resultTimer.value) {
              clearInterval(resultTimer.value)
              resultTimer.value = null
            }
          }
          if (
            result.value &&
            result.value.status === STATUS.AC &&
            canSubmitProblem.value === true
          ) {
            onSubmitProblem()
          }
        }, LeftListFrequency)
      }
    })
    .catch((err) => {
      console.log(err)
    })
})
watch(activeTab, () => {
  if (activeTab.value === PROBLEM_TAB_NAMES.RESULT && result.value === null) {
    //初次加载结果
    getProblemResult()
      .then(() => {
        if (result.value && result.value.status === STATUS.AC && canSubmitProblem.value === true) {
          onSubmitProblem()
        }
      })
      .catch((err) => {
        console.log(err)
      })
  }
})
onBeforeUnmount(() => {
  if (resultTimer.value) {
    clearInterval(resultTimer.value)
    resultTimer.value = null
  }
})
</script>
